<!doctype html>
<html lang="zh-CN">
<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    
    <meta name="referrer" content="no-referrer-when-downgrade">
    

    <title> | 早起的年轻人</title>
    <meta property="og:title" content=" - 早起的年轻人">
    <meta property="og:type" content="article">
        
        
    <meta name="Keywords" content="Flutter，golang,go语言,go语言笔记,飞雪无情,java,android,博客,项目管理,python,软件架构,公众号,小程序">
    <meta name="description" content="">
        
    <meta name="author" content="luckly">
    <meta property="og:url" content="https://luckly.work/post/flutter/%E5%B8%A6%E6%9C%89%E5%A4%9A%E4%B8%AA%E5%AF%BC%E8%88%AA%E5%99%A8%E7%9A%84-Flutter-%E5%BA%95%E9%83%A8%E5%AF%BC%E8%88%AA%E6%A0%8F%E6%A1%88%E4%BE%8B%E7%A0%94%E7%A9%B6/">
    <link rel="shortcut icon" href='/favicon.ico'  type="image/x-icon">

    <link rel="stylesheet" href='/css/normalize.css'>
    <link rel="stylesheet" href='/css/style.css'>
    <script type="text/javascript" src="//cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

    
    
    
        <link href="https://cdn.bootcdn.net/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css" rel="stylesheet">
    
    
    
    
        <link rel="stylesheet" href='/css/douban.css'>
    
        <link rel="stylesheet" href='/css/other.css'>
    
</head>

<link rel="stylesheet"
      href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/highlight.min.js"></script>
<body>
    <header id="header" class="clearfix">
    <div class="container">
        <div class="col-group">
            <div class="site-name ">
                
                    <a id="logo" href="https://luckly.work/">
                        早起的年轻人
                    </a>
                
                <p class="description">专注于Flutter、Android、Java、Go语言(golang)、移动互联网、项目管理、软件架构</p>
            </div>
            <div>
                <nav id="nav-menu" class="clearfix">
                    <a class="current" href="https://luckly.work/">首页</a>
                    
                    <a  href="https://luckly.work/categories/" title="分类">分类</a>
                    
                    <a  href="https://luckly.work/tags/" title="标签">标签</a>
                    
                    <a  href="https://luckly.work/about/" title="关于我">关于我</a>
                    
                    <a  href="https://github.com/ITmxs/" title="github">github</a>
                    
                </nav>
            </div>
        </div>
    </div>
</header>

    <div id="body">
        <div class="container">
            <div class="col-group">

                <div class="col-8" id="main">
                    
<div class="res-cons">
    <style type="text/css">
    .post-toc {
        position: fixed;
        width: 200px;
        margin-left: -210px;
        padding: 5px 10px;
        font-family: Athelas, STHeiti, Microsoft Yahei, serif;
        font-size: 12px;
        border: 1px solid rgba(0, 0, 0, .07);
        border-radius: 5px;
        background-color: rgba(255, 255, 255, 0.98);
        background-clip: padding-box;
        -webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, .125);
        box-shadow: 1px 1px 2px rgba(0, 0, 0, .125);
        word-wrap: break-word;
        white-space: nowrap;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
        z-index: 999;
        cursor: pointer;
        max-height: 70%;
        overflow-y: auto;
        overflow-x: hidden;
    }

    .post-toc .post-toc-title {
        width: 100%;
        margin: 0 auto;
        font-size: 20px;
        font-weight: 400;
        text-transform: uppercase;
        text-align: center;
    }

    .post-toc .post-toc-content {
        font-size: 15px;
    }

    .post-toc .post-toc-content>nav>ul {
        margin: 10px 0;
    }

    .post-toc .post-toc-content ul {
        padding-left: 20px;
        list-style: square;
        margin: 0.5em;
        line-height: 1.8em;
    }

    .post-toc .post-toc-content ul ul {
        padding-left: 15px;
        display: none;
    }

    @media print,
    screen and (max-width:1057px) {
        .post-toc {
            display: none;
        }
    }
</style>
<div class="post-toc" style="position: absolute; top: 188px;">
    <h2 class="post-toc-title">文章目录</h2>
    <div class="post-toc-content">
        <nav id="TableOfContents">
  <ul>
    <li><a href="#都是关于导航员的">都是关于导航员的</a></li>
    <li><a href="#ok-navigator告诉我你能做什么">Ok Navigator，告诉我你能做什么</a></li>
    <li><a href="#把东西放在一起">把东西放在一起</a></li>
    <li><a href="#多个导航器">多个导航器</a></li>
    <li><a href="#还有一件事">还有一件事</a></li>
    <li><a href="#wrap-up">Wrap up</a></li>
    <li><a href="#迁移指南">迁移指南</a></li>
  </ul>
</nav>
    </div>
</div>
<script type="text/javascript">
    $(document).ready(function () {
        var postToc = $(".post-toc");
        if (postToc.length) {
            var leftPos = $("#main").offset().left;
            if(leftPos<220){
                postToc.css({"width":leftPos-10,"margin-left":(0-leftPos)})
            }

            var t = postToc.offset().top - 20,
                a = {
                    start: {
                        position: "absolute",
                        top: t
                    },
                    process: {
                        position: "fixed",
                        top: 20
                    },
                };
            $(window).scroll(function () {
                var e = $(window).scrollTop();
                e < t ? postToc.css(a.start) : postToc.css(a.process)
            })
        }
    })
</script>
    <article class="post">
        <header>
            <h1 class="post-title"></h1>
        </header>
        <date class="post-meta meta-date">
            1年1月1日
        </date>
        
        
        <div class="post-meta">
            <span id="busuanzi_container_page_pv">|<span id="busuanzi_value_page_pv"></span><span>
                    阅读</span></span>
        </div>
        
        
        <div class="post-content">
            <p>今天我们来看看 Flutter 中的导航。</p>
<p>但不仅仅是任何无聊的导航。😉</p>
<p>不，女士们，先生们，我们会让这件事变得有趣。</p>
<p>这是一个带有<a href="https://docs.flutter.io/flutter/material/BottomNavigationBar-class.html">BottomNavigationBar</a>的应用程序：</p>
<p>
        <a data-fancybox="gallery" href="https://luckly007.oss-cn-beijing.aliyuncs.com/img/multiple-navigators-BottomNavigationBar-overview.png">
            <img class="mx-auto" alt="img" src="https://luckly007.oss-cn-beijing.aliyuncs.com/img/multiple-navigators-BottomNavigationBar-overview.png" />
        </a>
    </p>
<p>我们想要的是每个选项卡都有自己的导航堆栈。这是为了我们在切换标签时不会丢失导航历史记录。例子：</p>
<p>如何构建这个？精简版：</p>
<ul>
<li>创建一个带有<code>Scaffold</code>和的应用程序<code>BottomNavigationBar</code>。</li>
<li>在<code>Scaffold</code>正文中，<code>Stack</code>为每个选项卡创建一个子项。</li>
<li>每个孩子都是一个<code>Offstage</code>带有孩子的小部件<code>Navigator</code>。</li>
<li>不要忘记使用<code>WillPopScope</code>.</li>
</ul>
<p>想要更长更有趣的解释吗？首先，有几个免责声明：</p>
<ul>
<li>本文假设您熟悉 Flutter 中的导航。还有<a href="https://docs.flutter.io/flutter/widgets/Navigator-class.html"><code>Navigator</code></a>，<a href="https://docs.flutter.io/flutter/material/MaterialPageRoute-class.html"><code>MaterialPageRoute</code></a>和<a href="https://docs.flutter.io/flutter/material/MaterialApp-class.html"><code>MaterialApp</code></a>类更多的上下文。</li>
<li>使用 可以实现相同的结果<a href="https://api.flutter.dev/flutter/cupertino/CupertinoTabScaffold-class.html"><code>CupertinoTabScaffold</code></a>，它支持多个导航堆栈。但是<code>CupertinoTabScaffold</code>不是很可定制，所以在这里我们将推出一个定制的实现。</li>
<li><em>其中一些代码是实验性的。如果你知道更好的方法，请告诉我。</em></li>
</ul>
<p>好的，让我们开始吧。</p>
<h2 id="都是关于导航员的">都是关于导航员的</h2>
<p>所有 Flutter 应用程序总是定义一个<code>MaterialApp</code>. 通常这位于小部件树的根部：</p>
<pre><code>void main() =&gt; runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      home: App(),
    );
  }
}
</code></pre><p>然后，我们可以<code>App</code>像这样定义我们的类：</p>
<pre><code>// app.dart
class App extends StatefulWidget {
  @override
  State&lt;StatefulWidget&gt; createState() =&gt; AppState();
}

class AppState extends State&lt;App&gt; {

  var _currentTab = TabItem.red;

  void _selectTab(TabItem tabItem) {
    setState(() =&gt; _currentTab = tabItem);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _buildBody(),
      bottomNavigationBar: BottomNavigation(
        currentTab: _currentTab,
        onSelectTab: _selectTab,
      ),
    );
  }
  
  Widget _buildBody() {
    // TODO: return a widget representing a page
  }
}
</code></pre><p>此类使用<code>TabItem</code>定义三个单独选项卡的枚举：</p>
<pre><code>// tab_item.dart
import 'package:flutter/material.dart';

enum TabItem { red, green, blue }

const Map&lt;TabItem, String&gt; tabName = {
  TabItem.red: 'red',
  TabItem.green: 'green',
  TabItem.blue: 'blue',
};

const Map&lt;TabItem, MaterialColor&gt; activeTabColor = {
  TabItem.red: Colors.red,
  TabItem.green: Colors.green,
  TabItem.blue: Colors.blue,
};
</code></pre><p>上面的代码还使用两个地图为每个选项卡定义了<strong>标签</strong>和<strong>颜色</strong>。</p>
<hr>
<p>我们再来回顾一下<code>build()</code>这个<code>App</code>类的方法：</p>
<pre><code>  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _buildBody(),
      bottomNavigationBar: BottomNavigation(
        currentTab: _currentTab,
        onSelectTab: _selectTab,
      ),
    );
  }
</code></pre><p><code>BottomNavigation</code>是一个自定义小部件，它使用正确的颜色绘制三个选项卡，使用<a href="https://api.flutter.dev/flutter/material/BottomNavigationBar-class.html"><code>BottomNavigationBar</code></a>. 它接受<code>_currentTab</code>作为输入并<code>_selectTab</code>根据需要调用方法来更新状态。</p>
<p>这是这个类的样子：</p>
<pre><code>class BottomNavigation extends StatelessWidget {
  BottomNavigation({@required this.currentTab, @required this.onSelectTab});
  final TabItem currentTab;
  final ValueChanged&lt;TabItem&gt; onSelectTab;

  @override
  Widget build(BuildContext context) {
    return BottomNavigationBar(
      type: BottomNavigationBarType.fixed,
      items: [
        _buildItem(TabItem.red),
        _buildItem(TabItem.green),
        _buildItem(TabItem.blue),
      ],
      onTap: (index) =&gt; onSelectTab(
        TabItem.values[index],
      ),
    );
  }

  BottomNavigationBarItem _buildItem(TabItem tabItem) {
    return BottomNavigationBarItem(
      icon: Icon(
        Icons.layers,
        color: _colorTabMatching(tabItem),
      ),
      title: Text(tabName[tabItem]),
    );
  }

  Color _colorTabMatching(TabItem item) {
    return currentTab == item ? activeTabColor[item] : Colors.grey;
  }
}
</code></pre><p>当用户在选项卡之间切换时，这负责绘制<code>BottomNavigationBar</code>和调用<code>onSelectTab</code>。</p>
<hr>
<p>让我们回到我们的<code>App</code>小部件并实现一个<code>_buildBody()</code>为<code>Scaffold</code>主体返回小部件的方法：</p>
<p>为简单起见，我们可以通过添加<code>FlatButton</code>一个回调来推送新页面：</p>
<pre><code>Widget _buildBody() {
  return Container(
    color: activeTabColor[TabItem.red],
    alignment: Alignment.center,
    child: FlatButton(
      child: Text(
        'PUSH',
        style: TextStyle(fontSize: 32.0, color: Colors.white),
      ),
      onPressed: _push,
    )
  );
}

void _push() {
  Navigator.of(context).push(MaterialPageRoute(
    // we'll look at ColorDetailPage later
    builder: (context) =&gt; ColorDetailPage(
      color: activeTabColor[TabItem.red],
      title: tabName[TabItem.red],
    ),
  ));
}
</code></pre><p>该<code>_push()</code>方法是如何工作的？</p>
<ul>
<li><code>MaterialPageRoute</code> 负责创建要推送的新路由</li>
<li><code>Navigator.of(context)``Navigator</code>在小部件树中找到一个上方，并使用它来推送新路线。</li>
</ul>
<p>你可能想知道，<code>Navigator</code>widget 是从哪里来的？</p>
<p>我们还没有自己创建一个，我们<code>App</code>类的父类位于<code>MaterialApp</code>小部件树的根部。</p>
<p>事实证明，<code>MaterialApp</code>在<code>Navigator</code>内部创建自己的。</p>
<p>但是，如果我们只是<code>Navigator.of(context)</code>用来推送新的路由，就会发生意想不到的事情。</p>
<p><code>BottomNavigationBar</code>随着新页面的出现，整体及其内容滑开。不酷。🤨</p>
<p>
        <a data-fancybox="gallery" href="https://luckly007.oss-cn-beijing.aliyuncs.com/img/multiple-navigators-BottomNavigationBar-animation-slide.gif">
            <img class="mx-auto" alt="img" src="https://luckly007.oss-cn-beijing.aliyuncs.com/img/multiple-navigators-BottomNavigationBar-animation-slide.gif" />
        </a>
    </p>
<p>其实我们要的是要推的详细信息页面<strong>上</strong>的主页面，但要<strong>保持</strong>在<code>BottomNavigationBar</code>底部。</p>
<p>这不起作用，因为<code>Navigator.of(context)</code>找到了<code>BottomNavigatorBar</code>它自己的祖先。事实上，小部件树看起来像这样：</p>
<pre><code>▼ MyApp
 ▼ MaterialApp
  ▼ &lt;some other widgets&gt;
   ▼ Navigator
    ▼ &lt;some other widgets&gt;
     ▼ App
      ▼ Scaffold
       ▼ body: &lt;some other widgets&gt;
       ▼ BottomNavigationBar
</code></pre><p>如果我们打开 Flutter 检查器，它是：</p>
<p>
        <a data-fancybox="gallery" href="https://luckly007.oss-cn-beijing.aliyuncs.com/img/multiple-navigators-BottomNavigationBar-navigator-widget-tree.png">
            <img class="mx-auto" alt="img" src="https://luckly007.oss-cn-beijing.aliyuncs.com/img/multiple-navigators-BottomNavigationBar-navigator-widget-tree.png" />
        </a>
    </p>
<p>如果我们能使用<code>Navigator</code>这是<strong>不是</strong>我们的祖先<code>BottomNavigationBar</code>，然后按预期的东西会工作。</p>
<h2 id="ok-navigator告诉我你能做什么">Ok Navigator，告诉我你能做什么</h2>
<p>解决的办法是包裹<code>body</code>我们的<code>Scaffold</code>一个新的对象<code>Navigator</code>。</p>
<p>但在此之前，让我们介绍三个将用于显示最终 UI 的新类。</p>
<p>第一堂课被称为<code>TabNavigator</code>：</p>
<pre><code>// 1
class TabNavigatorRoutes {
  static const String root = '/';
  static const String detail = '/detail';
}

// 2
class TabNavigator extends StatelessWidget {
  TabNavigator({this.navigatorKey, this.tabItem});
  final GlobalKey&lt;NavigatorState&gt; navigatorKey;
  final TabItem tabItem;

  // 3
  Map&lt;String, WidgetBuilder&gt; _routeBuilders(BuildContext context,
      {int materialIndex: 500}) {
    return {
      TabNavigatorRoutes.root: (context) =&gt; ColorsListPage(
            color: TabHelper.color(tabItem),
            title: TabHelper.description(tabItem),
            onPush: (materialIndex) =&gt;
                _push(context, materialIndex: materialIndex),
          ),
      TabNavigatorRoutes.detail: (context) =&gt; ColorDetailPage(
            color: TabHelper.color(tabItem),
            title: TabHelper.description(tabItem),
            materialIndex: materialIndex,
          ),
    };
  }

  // 4
  @override
  Widget build(BuildContext context) {
    final routeBuilders = _routeBuilders(context);
    return Navigator(
      key: navigatorKey,
      initialRoute: TabNavigatorRoutes.root,
      onGenerateRoute: (routeSettings) {
        return MaterialPageRoute(
          builder: (context) =&gt; routeBuilders[routeSettings.name](context),
        );
      },
    );
  }

  // 5
  void _push(BuildContext context, {int materialIndex: 500}) {
    var routeBuilders = _routeBuilders(context, materialIndex: materialIndex);

    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) =&gt; routeBuilders[TabNavigatorRoutes.detail](context),
      ),
    );
  }
}
</code></pre><p>这是如何运作的？</p>
<ul>
<li>在第 1 步中，我们定义了两个路由名称：<code>/</code>和<code>/detail</code></li>
<li>在第 2 步中，我们为 定义了构造函数<code>TabNavigator</code>。这需要 a<code>navigatorKey</code>和 a <code>tabItem</code>。</li>
<li>请注意，<code>navigatorKey</code>具有类型<code>GlobalKey&lt;NavigatorState&gt;</code>。我们需要它来唯一标识整个应用程序中的导航器（<code>GlobalKey</code> <a href="https://docs.flutter.io/flutter/widgets/GlobalKey-class.html">在此处</a>阅读更多信息）。</li>
<li>在第 3 步中，我们定义了一个<code>_routeBuilders</code>方法，它将 a<code>WidgetBuilder</code>与我们定义的两条路由中的每一条相关联。稍后我们将查看<code>ColorsListPage</code>和<code>ColorDetailPage</code>。</li>
<li>在第 4 步，我们实现了<code>build()</code>返回一个新<code>Navigator</code>对象的方法。</li>
<li>这需要一个<code>key</code>和一个<code>initialRoute</code>参数。</li>
<li>它还有一个<code>onGenerateRoute</code>方法，每次需要生成路由时都会调用该方法。这利用了<code>_routeBuilders()</code>我们上面定义的方法。</li>
<li>在第 5 步，我们定义了一个<code>_push()</code>方法，用于推送带有<code>ColorDetailPage</code>.</li>
</ul>
<p>这是<code>ColorsListPage</code>课程：</p>
<pre><code>class ColorsListPage extends StatelessWidget {
  ColorsListPage({this.color, this.title, this.onPush});
  final MaterialColor color;
  final String title;
  final ValueChanged&lt;int&gt; onPush;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(
            title,
          ),
          backgroundColor: color,
        ),
        body: Container(
          color: Colors.white,
          child: _buildList(),
        ));
  }

  final List&lt;int&gt; materialIndices = [900, 800, 700, 600, 500, 400, 300, 200, 100, 50];

  Widget _buildList() {
    return ListView.builder(
        itemCount: materialIndices.length,
        itemBuilder: (BuildContext content, int index) {
          int materialIndex = materialIndices[index];
          return Container(
            color: color[materialIndex],
            child: ListTile(
              title: Text('$materialIndex', style: TextStyle(fontSize: 24.0)),
              trailing: Icon(Icons.chevron_right),
              onTap: () =&gt; onPush(materialIndex),
            ),
          );
        });
  }
}
</code></pre><p>这个类的目的是显示<code>ListView</code>输入的所有颜色阴影<code>MaterialColor</code>。<code>MaterialColor</code>只不过是<code>ColorSwatch</code>有十种不同色调的。</p>
<p>为了完整起见，这里是<code>ColorDetailPage</code>：</p>
<pre><code>class ColorDetailPage extends StatelessWidget {
  ColorDetailPage({this.color, this.title, this.materialIndex: 500});
  final MaterialColor color;
  final String title;
  final int materialIndex;

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        backgroundColor: color,
        title: Text(
          '$title[$materialIndex]',
        ),
      ),
      body: Container(
        color: color[materialIndex],
      ),
    );
  }
}
</code></pre><p>这个很简单：它只显示一个页面，其中包含<code>AppBar</code>从 input 中选择的颜色阴影<code>MaterialColor</code>。它看起来像这样：</p>
<p>
        <a data-fancybox="gallery" href="https://luckly007.oss-cn-beijing.aliyuncs.com/img/multiple-navigators-BottomNavigationBar-red-detail.png">
            <img class="mx-auto" alt="img" src="https://luckly007.oss-cn-beijing.aliyuncs.com/img/multiple-navigators-BottomNavigationBar-red-detail.png" />
        </a>
    </p>
<h2 id="把东西放在一起">把东西放在一起</h2>
<p>现在我们有了我们的<code>TabNavigator</code>，让我们回到我们的<code>App</code>并使用它：</p>
<pre><code>  final navigatorKey = GlobalKey&lt;NavigatorState&gt;();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: TabNavigator(
        navigatorKey: navigatorKey,
        tabItem: currentTab,
      ),
      bottomNavigationBar: BottomNavigation(
        currentTab: currentTab,
        onSelectTab: _selectTab,
      ),
    );
  }
</code></pre><ul>
<li>首先，我们定义一个<code>navigatorKey</code>.</li>
<li>然后在我们的<code>build()</code>方法中，我们<code>TabNavigator</code>用它创建一个并传入<code>currentTab</code>.</li>
</ul>
<p>如果我们现在运行该应用程序，我们可以看到在选择列表项时<strong>push</strong>工作正常，并且<code>BottomNavigationBar</code>保持原位。好极了！😀</p>
<p>但是有一个问题。在选项卡之间切换似乎不起作用，因为我们总是在<code>Scaffold</code>正文中显示红页。</p>
<h2 id="多个导航器">多个导航器</h2>
<p>这是因为我们定义了一个新的导航器，但它在所有三个选项卡中<strong>共享</strong>。</p>
<p><strong>请记住</strong>：我们想要的是每个选项卡的独立导航堆栈！</p>
<p>让我们通过创建<strong>三个</strong>导航器来解决这个问题：</p>
<pre><code>class App extends StatefulWidget {
  @override
  State&lt;StatefulWidget&gt; createState() =&gt; AppState();
}

class AppState extends State&lt;App&gt; {

  var _currentTab = TabItem.red;
  final _navigatorKeys = {
    TabItem.red: GlobalKey&lt;NavigatorState&gt;(),
    TabItem.green: GlobalKey&lt;NavigatorState&gt;(),
    TabItem.blue: GlobalKey&lt;NavigatorState&gt;(),
  };

  void _selectTab(TabItem tabItem) {
    setState(() =&gt; _currentTab = tabItem);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(children: &lt;Widget&gt;[
        _buildOffstageNavigator(TabItem.red),
        _buildOffstageNavigator(TabItem.green),
        _buildOffstageNavigator(TabItem.blue),
      ]),
      bottomNavigationBar: BottomNavigation(
        currentTab: _currentTab,
        onSelectTab: _selectTab,
      ),
    );
  }

  Widget _buildOffstageNavigator(TabItem tabItem) {
    return Offstage(
      offstage: _currentTab != tabItem,
      child: TabNavigator(
        navigatorKey: navigatorKeys[tabItem],
        tabItem: tabItem,
      ),
    );
  }
}
</code></pre><p>一些注意事项：</p>
<ul>
<li>在<code>AppState</code>类中，我们定义了全局导航键的映射。我们需要这个来确保我们使用多个导航器。</li>
<li>我们的身体<code>Scaffold</code>现在是一个<code>Stack</code>有三个孩子的人。</li>
<li>每个孩子都建立在<code>_buildOffstageNavigator()</code>方法中。</li>
<li>这使用<a href="https://docs.flutter.io/flutter/widgets/Offstage-class.html"><code>Offstage</code></a>带有 child的小部件<code>TabNavigator</code>。<code>offstage</code>如果呈现的选项卡与当前选项卡不匹配，则该属性为 true。</li>
<li>我们传递<code>navigatorKey[tabItem]</code>给 our<code>TabNavigator</code>以确保每个选项卡都有一个单独的导航键。</li>
</ul>
<p>如果我们编译并运行应用程序，现在一切都按预期工作。我们可以独立地<strong>推送</strong>/<strong>弹出</strong>每个导航器，并且后台导航器保持它们的状态。🚀</p>
<h2 id="还有一件事">还有一件事</h2>
<p>如果我们在 Android 上运行该应用程序，当我们按下后退按钮时，我们会观察到一个有趣的行为：</p>
<p>
        <a data-fancybox="gallery" href="https://codewithandrea.com/articles/multiple-navigators-bottom-navigation-bar/images/multiple-navigators-BottomNavigationBar-back-button-not-handled.gif">
            <img class="mx-auto" alt="img" src="https://codewithandrea.com/articles/multiple-navigators-bottom-navigation-bar/images/multiple-navigators-BottomNavigationBar-back-button-not-handled.gif" />
        </a>
    </p>
<p>该应用程序被关闭，我们回到主屏幕！</p>
<p>这是因为我们还没有指定应该如何处理后退按钮。</p>
<p>让我们解决这个问题：</p>
<pre><code>  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async =&gt;
          !await navigatorKeys[currentTab].currentState.maybePop(),
      child: Scaffold(
        body: Stack(children: &lt;Widget&gt;[
          _buildOffstageNavigator(TabItem.red),
          _buildOffstageNavigator(TabItem.green),
          _buildOffstageNavigator(TabItem.blue),
        ]),
        bottomNavigationBar: BottomNavigation(
          currentTab: currentTab,
          onSelectTab: _selectTab,
        ),
      ),
    );
  }
</code></pre><p>这是通过<a href="https://docs.flutter.io/flutter/widgets/WillPopScope-class.html"><code>WillPopScope</code></a>小部件完成的，该小部件控制如何解除路由。从文档<code>WillPopScope</code>：</p>
<blockquote>
<p>注册一个回调以否决用户试图关闭封闭的 [ModalRoute]</p>
</blockquote>
<p>请注意如果当前导航器可以弹出，则<code>onWillPop()</code>回调如何返回<code>false</code>，<code>true</code>否则。</p>
<p>如果我们再次运行应用程序，我们可以看到按下后退按钮会关闭所有推送的路由，<strong>只有</strong>再次按下它我们<strong>才会</strong>离开应用程序。</p>
<p>需要注意的一点是，当我们在 Android 上推送新路由时，它会从底部滑入。相反，惯例是在 iOS 上从右侧滑入。</p>
<p>感谢<a href="https://github.com/brianegan"><strong>Brian Egan</strong></a>找到了一种让导航器工作的方法。他的想法是使用<code>Stack</code>带<code>Offstage</code>小部件来保留导航器的状态。</p>
<h2 id="wrap-up">Wrap up</h2>
<p>今天，我们已经了解了扑导航，以及如何结合一个很好的协议<code>BottomNavigationBar</code>，<code>Stack</code>，<code>Offstage</code>和<code>Navigator</code>小部件，使多个导航堆栈。</p>
<p>使用<code>Offstage</code>小部件可确保我们所有的导航器在保留在小部件树中时保留其状态。这可能会带来一些性能损失，因此如果您选择使用它们，我建议您分析您的应用程序。</p>
<p>注意：<code>Offstage</code>我们可以使用 a <code>CupertinoTabScaffold</code>，而不是推出我们自己的带有小部件的导航器，它已经内置了对独立导航堆栈的支持。但与 material 不同的是<code>Scaffold</code>，<code>CupertinoTabScaffold</code>它的 API 有限，您无法使用它来添加浮动操作按钮。</p>
<h2 id="迁移指南">迁移指南</h2>
<p>迁移前的代码：</p>
<p><em>content_copy</em></p>
<pre><code>BottomNavigationBarItem(
  icon: Icons.add,
  title: Text('add'),
)
</code></pre><p>迁移后的代码：</p>
<p><em>content_copy</em></p>
<pre><code>BottomNavigationBarItem(
  icon: Icons.add,
  label: 'add',
)
</code></pre>
        </div>

        
<div class="post-archive">
    <ul class="post-copyright">
        <li><strong>原文作者：</strong><a rel="author" href="https://luckly.work/">luckly</a></li>
        <li style="word-break:break-all"><strong>原文链接：</strong><a href="https://luckly.work/post/flutter/%E5%B8%A6%E6%9C%89%E5%A4%9A%E4%B8%AA%E5%AF%BC%E8%88%AA%E5%99%A8%E7%9A%84-Flutter-%E5%BA%95%E9%83%A8%E5%AF%BC%E8%88%AA%E6%A0%8F%E6%A1%88%E4%BE%8B%E7%A0%94%E7%A9%B6/">https://luckly.work/post/flutter/%E5%B8%A6%E6%9C%89%E5%A4%9A%E4%B8%AA%E5%AF%BC%E8%88%AA%E5%99%A8%E7%9A%84-Flutter-%E5%BA%95%E9%83%A8%E5%AF%BC%E8%88%AA%E6%A0%8F%E6%A1%88%E4%BE%8B%E7%A0%94%E7%A9%B6/</a></li>
        <li><strong>版权声明：</strong>本作品采用<a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/">知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议</a>进行许可，非商业转载请注明出处（作者，原文链接），商业转载请联系作者获得授权。</li>
    </ul>
</div>
<br/>



        

<div class="post-archive">
    <h2>See Also</h2>
    <ul class="listing">
        
        <li><a href="/post/%E4%BF%A1%E6%81%AF/%E5%8F%98%E6%9B%B4%E7%AE%A1%E7%90%86/">变更管理</a></li>
        
        <li><a href="/post/%E4%BF%A1%E6%81%AF/%E7%9F%A5%E8%AF%86%E7%AE%A1%E7%90%86/">知识管理</a></li>
        
        <li><a href="/post/%E4%BF%A1%E6%81%AF/%E6%96%87%E6%A1%A3%E5%92%8C%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86/">文档和配置管理</a></li>
        
        <li><a href="/post/%E4%BF%A1%E6%81%AF/%E5%90%88%E5%90%8C%E7%AE%A1%E7%90%86/">合同管理</a></li>
        
        <li><a href="/post/%E4%BF%A1%E6%81%AF/%E9%87%87%E8%B4%AD%E7%AE%A1%E7%90%86/">采购管理</a></li>
        
    </ul>
</div>


        <div class="post-meta meta-tags">
            
            没有标签
            
        </div>
    </article>
    
    

    
    
    <div class="post bg-white">
      <script src="https://utteranc.es/client.js"
            repo= "https://github.com/ITmxs/repo"
            issue-term="pathname"
            theme="github-light"
            crossorigin="anonymous"
            async>
      </script>
    </div>
    
</div>

                    <footer id="footer">
    <div>
        &copy; 2021 <a href="https://luckly.work/">早起的年轻人 By luckly</a>
        
        | <a rel="nofollow" target="_blank" href="http://beian.miit.gov.cn/">粤ICP备2021号-1</a>
        
    </div>
    <br />
    <div>
        <div class="github-badge">
            <a href="https://juejin.cn/user/3843548384077192" target="_black" rel="nofollow"><span class="badge-subject">Powered by</span><span class="badge-value bg-blue">掘金</span></a>
        </div>
        <div class="github-badge">
            <a href="https://space.bilibili.com/480883651" target="_black"><span class="badge-subject">Design by</span><span class="badge-value bg-brightgreen">早起的年轻人</span></a>
        </div>
        <div class="github-badge">
            <a href="https://cloud.tencent.com/developer/user/6702670" target="_black"><span class="badge-subject">Theme</span><span class="badge-value bg-yellowgreen">云社区</span></a>
        </div>
    </div>
</footer>


    
    <script type="text/javascript">
        window.MathJax = {
            tex2jax: {
                inlineMath: [['$', '$']],
                processEscapes: true
                }
            };
    </script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async></script><script src="https://cdn.bootcdn.net/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js"></script>

<a id="rocket" href="#top"></a>
<script type="text/javascript" src='/js/totop.js?v=0.0.0' async=""></script>



    <script type="text/javascript" src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" async></script>




    <script src='/js/douban.js'></script>
    <script src="/js/copy-to-clipboard.js"></script>

                </div>

                <div id="secondary">
    <section class="widget">
        <form id="search" action='https://luckly.work/search/' method="get" accept-charset="utf-8" target="_blank" _lpchecked="1">
      
      <input type="text" name="q" maxlength="20" placeholder="Search">
      <input type="hidden" name="sitesearch" value="https://luckly.work/">
      <button type="submit" class="submit icon-search"></button>
</form>
    </section>
    
    <section class="widget">
        <h3 class="widget-title">最近文章</h3>
<ul class="widget-list">
    
    <li>
        <a href="https://luckly.work/post/%E4%BF%A1%E6%81%AF/%E5%8F%98%E6%9B%B4%E7%AE%A1%E7%90%86/" title="变更管理">变更管理</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/%E4%BF%A1%E6%81%AF/%E7%9F%A5%E8%AF%86%E7%AE%A1%E7%90%86/" title="知识管理">知识管理</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/%E4%BF%A1%E6%81%AF/%E6%96%87%E6%A1%A3%E5%92%8C%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86/" title="文档和配置管理">文档和配置管理</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/%E4%BF%A1%E6%81%AF/%E5%90%88%E5%90%8C%E7%AE%A1%E7%90%86/" title="合同管理">合同管理</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/%E4%BF%A1%E6%81%AF/%E9%87%87%E8%B4%AD%E7%AE%A1%E7%90%86/" title="采购管理">采购管理</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/%E4%BF%A1%E6%81%AF/%E9%A3%8E%E9%99%A9%E7%AE%A1%E7%90%86/" title="风险管理">风险管理</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/%E4%BF%A1%E6%81%AF/%E6%B2%9F%E9%80%9A%E7%AE%A1%E7%90%86%E5%92%8C%E5%B9%B2%E7%B3%BB%E4%BA%BA%E7%AE%A1%E7%90%86/" title="沟通管理和干系人管理">沟通管理和干系人管理</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/%E4%BF%A1%E6%81%AF/%E4%BA%BA%E5%8A%9B%E8%B5%84%E6%BA%90%E7%AE%A1%E7%90%86/" title="人力资源管理">人力资源管理</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/%E4%BF%A1%E6%81%AF/%E8%B4%A8%E9%87%8F%E7%AE%A1%E7%90%86/" title="质量管理">质量管理</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/%E4%BF%A1%E6%81%AF/%E8%8C%83%E5%9B%B4%E7%AE%A1%E7%90%86/" title="范围管理">范围管理</a>
    </li>
    
</ul>
    </section>

    
<section class="widget">
    <h3 class="widget-title" style="color:red">福利派送</h3>
    <ul class="widget-list">
        
        <li>
            <a href="https://blog.csdn.net/qq_39132095?spm=1001.2101.3001.5343" title="我的CSDN" target="_blank" style="color:red">
                
                    <img src="https://luckly007.oss-cn-beijing.aliyuncs.com/img/flutter.png">
                
            </a>
        </li>
        
        <li>
            <a href="https://space.bilibili.com/480883651" title="我的哔哩哔哩" target="_blank" style="color:red">
                
                    <img src="https://luckly007.oss-cn-beijing.aliyuncs.com/img/flutter.png">
                
            </a>
        </li>
        
        <li>
            <a href="https://www.zhihu.com/people/yimi-yang-guang-96-65" title="我的知乎" target="_blank" style="color:red">
                
                    <img src="https://luckly007.oss-cn-beijing.aliyuncs.com/img/flutter.png">
                
            </a>
        </li>
        
    </ul>
</section>


    <section class="widget">
        <h3 class="widget-title"><a href='/categories/'>分类</a></h3>
<ul class="widget-list">
    
    <li><a href="https://luckly.work/categories/Go/">Go (1)</a></li>
    
    <li><a href="https://luckly.work/categories/Mysql/">Mysql (1)</a></li>
    
    <li><a href="https://luckly.work/categories/Nginx/">Nginx (1)</a></li>
    
    <li><a href="https://luckly.work/categories/YouTube%E8%A7%86%E9%A2%91%E4%B8%8B%E8%BD%BD/">YouTube视频下载 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/android/">android (1)</a></li>
    
    <li><a href="https://luckly.work/categories/dart/">dart (15)</a></li>
    
    <li><a href="https://luckly.work/categories/Flutter/">Flutter (201)</a></li>
    
    <li><a href="https://luckly.work/categories/git/">git (3)</a></li>
    
    <li><a href="https://luckly.work/categories/Go/">Go (4)</a></li>
    
    <li><a href="https://luckly.work/categories/ios/">ios (1)</a></li>
    
    <li><a href="https://luckly.work/categories/linux/">linux (1)</a></li>
    
    <li><a href="https://luckly.work/categories/read/">读书笔记 (6)</a></li>
    
    <li><a href="https://luckly.work/categories/redis/">redis (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%B8%AA%E4%BA%BA%E8%B5%84%E6%96%99/">个人资料 (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%B9%A6%E5%8D%95/">书单 (8)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%B9%A6%E8%AF%84/">书评 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F%E7%AE%A1%E7%90%86%E5%B8%88/">信息系统管理师 (8)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86%E5%B8%88/">信息系统项目管理师 (14)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%8E%9F%E5%88%99/">原则 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%8E%9F%E7%94%9F%E9%80%9A%E8%AE%AF/">原生通讯 (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%9F%BA%E7%A1%80/">基础 (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%A4%8D%E5%88%A9%E6%95%88%E5%BA%94/">复利效应 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B/">安装教程 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%B0%91%E6%9C%89%E4%BA%BA%E8%B5%B0%E7%9A%84%E8%B7%AF/">少有人走的路 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%BF%83%E8%AF%AD/">心语 (3)</a></li>
    
    <li><a href="https://luckly.work/categories/%E6%8F%92%E4%BB%B6/">插件 (4)</a></li>
    
    <li><a href="https://luckly.work/categories/%E6%95%99%E5%AD%A6/">教学 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%8E%8B%E9%98%B3%E6%98%8E/">王阳明 (3)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%94%B5%E5%AD%90%E4%B9%A6/">电子书 (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%99%BB%E9%99%86%E8%A1%A8%E5%8D%95/">登陆表单 (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%A8%BB%E7%9B%9B%E5%92%8C%E5%A4%AB/">稻盛和夫 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%A9%B7%E7%88%B8%E7%88%B8%E5%AF%8C%E7%88%B8%E7%88%B8/">穷爸爸富爸爸 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%B2%BE%E8%BF%9B/">精进 (3)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%BC%96%E7%A8%8B/">编程 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%B4%A2%E5%8A%A1%E8%87%AA%E7%94%B1%E4%B9%8B%E8%B7%AF/">财务自由之路 (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%B7%91%E6%AD%A5/">跑步 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%B7%AF%E7%94%B1%E4%BC%A0%E5%8F%82/">路由传参 (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%B7%AF%E7%BA%BF/">路线 (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%BD%AF%E4%BB%B6%E5%AE%9E%E6%96%BD/">软件实施 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E9%98%B3%E6%98%8E%E5%BF%83%E5%AD%A6/">阳明心学 (3)</a></li>
    
    <li><a href="https://luckly.work/categories/%E9%A1%B9%E7%9B%AE/">项目 (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E9%AD%85%E5%8A%9B/">魅力 (1)</a></li>
    
</ul>
    </section>

    <section class="widget">
        <h3 class="widget-title"><a href='/tags/'>标签</a></h3>
<div class="tagcloud">
    
    <a href="https://luckly.work/tags/go/">go</a>
    
    <a href="https://luckly.work/tags/Mysql/">Mysql</a>
    
    <a href="https://luckly.work/tags/Nginx/">Nginx</a>
    
    <a href="https://luckly.work/tags/YouTube%E8%A7%86%E9%A2%91%E4%B8%8B%E8%BD%BD/">YouTube视频下载</a>
    
    <a href="https://luckly.work/tags/android/">android</a>
    
    <a href="https://luckly.work/tags/dart/">dart</a>
    
    <a href="https://luckly.work/tags/flutter/">flutter</a>
    
    <a href="https://luckly.work/tags/git/">git</a>
    
    <a href="https://luckly.work/tags/go/">go</a>
    
    <a href="https://luckly.work/tags/ios/">ios</a>
    
    <a href="https://luckly.work/tags/linux/">linux</a>
    
    <a href="https://luckly.work/tags/redis/">redis</a>
    
    <a href="https://luckly.work/tags/%E4%B8%AA%E4%BA%BA%E8%B5%84%E6%96%99/">个人资料</a>
    
    <a href="https://luckly.work/tags/%E4%B9%A6%E5%8D%95/">书单</a>
    
    <a href="https://luckly.work/tags/%E4%B9%A6%E8%AF%84/">书评</a>
    
    <a href="https://luckly.work/tags/%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F%E7%AE%A1%E7%90%86%E5%B8%88/">信息系统管理师</a>
    
    <a href="https://luckly.work/tags/%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86%E5%B8%88/">信息系统项目管理师</a>
    
    <a href="https://luckly.work/tags/%E5%85%A5%E9%97%A8/">入门</a>
    
    <a href="https://luckly.work/tags/%E5%8E%9F%E5%88%99/">原则</a>
    
    <a href="https://luckly.work/tags/%E5%8E%9F%E7%94%9F%E9%80%9A%E8%AE%AF/">原生通讯</a>
    
    <a href="https://luckly.work/tags/%E5%9F%BA%E7%A1%80/">基础</a>
    
    <a href="https://luckly.work/tags/%E5%A4%8D%E5%88%A9%E6%95%88%E5%BA%94/">复利效应</a>
    
    <a href="https://luckly.work/tags/%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B/">安装教程</a>
    
    <a href="https://luckly.work/tags/%E5%B0%91%E6%9C%89%E4%BA%BA%E8%B5%B0%E7%9A%84%E8%B7%AF/">少有人走的路</a>
    
    <a href="https://luckly.work/tags/%E5%BF%83%E8%AF%AD/">心语</a>
    
    <a href="https://luckly.work/tags/%E6%8F%92%E4%BB%B6/">插件</a>
    
    <a href="https://luckly.work/tags/%E6%95%99%E5%AD%A6/">教学</a>
    
    <a href="https://luckly.work/tags/%E7%8E%8B%E9%98%B3%E6%98%8E/">王阳明</a>
    
    <a href="https://luckly.work/tags/%E7%94%B5%E5%AD%90%E4%B9%A6/">电子书</a>
    
    <a href="https://luckly.work/tags/%E7%99%BB%E9%99%86%E8%A1%A8%E5%8D%95/">登陆表单</a>
    
    <a href="https://luckly.work/tags/%E7%A8%BB%E7%9B%9B%E5%92%8C%E5%A4%AB/">稻盛和夫</a>
    
    <a href="https://luckly.work/tags/%E7%A9%B7%E7%88%B8%E7%88%B8%E5%AF%8C%E7%88%B8%E7%88%B8/">穷爸爸富爸爸</a>
    
    <a href="https://luckly.work/tags/%E7%B2%BE%E8%BF%9B/">精进</a>
    
    <a href="https://luckly.work/tags/%E7%BC%96%E7%A8%8B/">编程</a>
    
    <a href="https://luckly.work/tags/%E8%AF%97/">诗</a>
    
    <a href="https://luckly.work/tags/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/">读书笔记</a>
    
    <a href="https://luckly.work/tags/%E8%B4%A2%E5%8A%A1%E8%87%AA%E7%94%B1%E4%B9%8B%E8%B7%AF/">财务自由之路</a>
    
    <a href="https://luckly.work/tags/%E8%B7%91%E6%AD%A5/">跑步</a>
    
    <a href="https://luckly.work/tags/%E8%B7%AF%E7%94%B1%E4%BC%A0%E5%8F%82/">路由传参</a>
    
    <a href="https://luckly.work/tags/%E8%B7%AF%E7%BA%BF/">路线</a>
    
    <a href="https://luckly.work/tags/%E8%BD%AF%E4%BB%B6%E5%AE%9E%E6%96%BD/">软件实施</a>
    
    <a href="https://luckly.work/tags/%E9%80%9A%E8%AE%AF%E5%BD%95/">通讯录</a>
    
    <a href="https://luckly.work/tags/%E9%98%B3%E6%98%8E%E5%BF%83%E5%AD%A6/">阳明心学</a>
    
    <a href="https://luckly.work/tags/%E9%A1%B9%E7%9B%AE/">项目</a>
    
    <a href="https://luckly.work/tags/%E9%AD%85%E5%8A%9B/">魅力</a>
    
</div>
    </section>

    
<section class="widget">
    <h3 class="widget-title">友情链接</h3>
    <ul class="widget-list">
        
        <li>
            <a target="_blank" href="https://www.flysnow.org/" title="飞雪无情的博客">飞雪无情的博客</a>
        </li>
        
        <li>
            <a target="_blank" href="http://yuedu.baidu.com/ebook/14a722970740be1e640e9a3e" title="Android Gradle权威指南">Android Gradle权威指南</a>
        </li>
        
    </ul>
</section>


    <section class="widget">
        <h3 class="widget-title">其它</h3>
        <ul class="widget-list">
            <li><a href="https://luckly.work/index.xml">文章 RSS</a></li>
        </ul>
    </section>
</div>
            </div>
        </div>
    </div>
</body>

</html>